home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d18
/
tpa2_a.arc
/
FIND.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-04-28
|
7KB
|
173 lines
{═════════════════════════════ FIND.PAS ═════════════════════════════}
{ Usage: Find (From Editor, just Run) }
{═════════════════════════════ FIND.PAS ═════════════════════════════}
{- This demonstration illustrates the advantage of using assembly }
{- language to improve execution speed of time consuming operations. }
{- Searches about 30,000 bytes of memory for the string FindString }
{- and repeats 10 times. On my 8MHz 8086 based machine this takes }
{- 0.7 seconds in assembly language and about 10 times that long in }
{- Pascal. You can dramatically improve operations on large text }
{- files by using BlockRead (into a Buffer), Find(BufPtr,256,CrLf) }
{- (to find line ends), and Move (into a standard String variable) }
{- in place of repeated calls to ReadLn. }
{═══════════════════════════════ Find ═══════════════════════════════}
{ Search memory (case sensitive) for string FindStr. Return number }
{ of characters skipped to find a match, or SearchLimit if no match }
{ Checks entire FindStr even if end of FindStr is beyond SearchLimit }
{ Thus: Find(StartAddr,1,FindStr)=0 only if FindStr is at StartAddr }
{═══════════════════════════════ Find ═══════════════════════════════}
TYPE St63= String[63];
FUNCTION Find( VAR StartAddr; SearchLimit:INTEGER; FindStr:St63 ): INTEGER;
BEGIN
ASSEMBLE
;- NOTE that the [Bp] specification required to reference parameters
;- and local variables is supplied automatically by TP&Asm.
;- You may code the [Bp]'s explicitly if you prefer ( StartAddr[Bp] ),
;- and you may disable presumptions for "WYSIWYG" assembly.
;- Remember - TP&Asm knows how to find all your Pascal variables because
;- it assembles during the compile step!
Cld ; Set forward direction for Lodsb/w and Cmpsb
Mov Cx,SearchLimit ; Maximum bytes to search
Mov Dx,Cx ; Save in Dx
Les Di,StartAddr ; point Es:[Di] to StartAddr
Lea Si,FindStr ; NOTE: String Value is located in Stack Segment
Lodsw ; Al <-- Ss:[Si], Ah <-- Ss:[Si+1], Si <-- Si+2
;- Lodsw normally loads from Ds:[Si], however TP&Asm correctly presumes
;- and supplies the Ss override necessary to obtain access to FindStr.
;- You may code the override explicitly if you prefer ( Ss LodsW ),
;- and you may disable presumptions for "WYSIWYG" assembly.
Xchg Ah,Al ; Now FindStrLen is in Ah, FindStr[1] is in Al
ScanLoop:
RepNE Scasb ; Fast Scan Es:[Di] for Al; Di <-- [match]+1
jNE Finish ; If no match found, return SearchLimit saved in Dx
Push Cx,Di ; Save Cx & Di in case this 'Find' is premature
Xor Ch,Ch ; Clear Ch
Mov Cl,Ah ; Load FindStrLen
Dec Cl ; FindStr[1] has already been checked
L1:
CmpsB ; Compare Ss:[Si] =? Es:[Di], Inc Di, Inc Si
LoopE L1 ; Repeat while equal, Dec Cx
Pop Di,Cx ; Restore Cx & Di, Find NEXT occurrance of Al
jNE ScanLoop ; - Jmp only if exitted LoopE with NE (miscompare)
Inc Cx ; Arrive here if string found
Sub Dx,Cx ; Find number of bytes skipped
Finish:
Mov Find,Dx ; Put in function result
END; {Assemble}
END; {FUNCTION Find}
{═════════════════════════════ PasFind ══════════════════════════════}
{ Same as FUNCTION Find but written in Pascal rather than Assembly }
{═════════════════════════════ PasFind ══════════════════════════════}
FUNCTION PasFind(VAR StartAddr; SearchLimit:INTEGER; FindStr:St63):INTEGER;
VAR m,n:INTEGER;
FindArray: ARRAY[0..$7FF0] OF CHAR Absolute StartAddr;
BEGIN
m := 0;
FOR n := 0 TO SearchLimit DO BEGIN
IF FindArray[n] = FindStr[1] THEN BEGIN
WHILE FindArray[n+m]=FindStr[1+m] DO m:=m+1;
IF m >= Length(FindStr) THEN BEGIN
PasFind := n; Exit;
END; {IF m >= Length(FindStr) THEN }
m := 0;
END; {IF FindArray[n] = FindStr[1] THEN }
END; {FOR n := 0 TO SearchLimit DO }
PasFind := SearchLimit;
END; {FUNCTION PasFind}
{═════════════════════════════ GetTime ══════════════════════════════}
{ Compatible with Version 4 & 5 DOS Unit Procedure. }
{═════════════════════════════ GetTime ══════════════════════════════}
PROCEDURE GetTime( VAR Hour, Minute, Second, Hundredth: INTEGER);
VAR HrMin, SecHn: INTEGER;
BEGIN
Assemble
Mov Ah,2Ch
Int 21h ; Get System time into Cx:Dx
Xor Ah,Ah
Mov Al,Ch ; Now Ax = System hour
;- Use the parameter pointers to store VAR results in assembly language ..
Les Di,Hour ; Es:[Di] points to Hour
Es Mov [Di],Ax ; Save Hour value in Es:[Di]
;- .. or save into local variables ..
Mov HrMin,Cx
Mov SecHn,Dx
End; {Assemble}
{- .. and let the compiler do the work: -}
Minute := Lo(HrMin);
Second := Hi(SecHn);
Hundredth := Lo(SecHn);
END; {PROCEDURE GetTime}
{══════════════════ A couple of Display Functions ═══════════════════}
TYPE Str2 = STRING[2];
FUNCTION TwoDgt(N: INTEGER): Str2; VAR Tmp: Str2;
BEGIN
Str(N:2,Tmp); IF N<10 THEN Tmp[1] := '0'; TwoDgt := Tmp;
END; {FUNCTION TwoDgt}
TYPE Str12 = STRING[12];
FUNCTION TimeDisplay: Str12;
VAR Hour, Minute, Second, Hundredth: INTEGER;
BEGIN
GetTime( Hour, Minute, Second, Hundredth );
TimeDisplay := TwoDgt(Hour) +':' +TwoDgt(Minute) +':' +TwoDgt(Second)
+'.' +TwoDgt(Hundredth);
END; {TimeDisplay}
{══════════════════ A couple of Display Functions ═══════════════════}
VAR
BigArray: ARRAY[1..30000] OF BYTE;
FindString: String[80];
FindLoc,n : INTEGER;
CONST
MaxSearch = 32000;
Repeats = 10;
BEGIN
FillChar(BigArray,SizeOf(BigArray),' ');
FindString := 'Find This String';
WRITELN('Asm Find Test:');
WRITELN('Start search at ',TimeDisplay);
FOR n := 1 TO Repeats DO FindLoc := Find(BigArray,MaxSearch,FindString);
IF FindLoc = MaxSearch THEN WRITE('String NOT FOUND!')
ELSE WRITE('Found at ',FindLoc);
WRITELN(' Should Find at: ', 1+ SizeOf(BigArray));
WRITELN('Finish search at ',TimeDisplay);
WRITELN;
WRITELN('Pas Find Test:');
WRITELN('Start search at ',TimeDisplay);
FOR n := 1 TO Repeats DO FindLoc := PasFind(BigArray,MaxSearch,FindString);
IF FindLoc = MaxSearch THEN WRITE('String NOT FOUND!')
ELSE WRITE('Found at ',FindLoc);
WRITELN(' Should Find at: ', 1+ SizeOf(BigArray));
WRITELN('Finish search at ',TimeDisplay);
WRITELN;
END.